package com.webex.ta.hydra.gui.table.celleditor;

import com.webex.ta.hydra.gui.util.ListScrollingUtil;
import com.webex.ta.hydra.core.Command;
import com.webex.ta.hydra.core.KeywordRegistry;
import com.webex.ta.hydra.util.HydraUtils;

import javax.swing.*;
import javax.swing.event.DocumentListener;
import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import java.util.EventObject;

/**
 * Author: Vegaz
 * Date: 2010-11-22
 * Time: 12:43:17
 */
public class KeywordEditor2 extends AbstractCellEditor implements HydraTableCellEditor {
    JTextField textField;
    JList list;
    KeywordListModel model;
    JScrollPane scroll;
    int maxHeight;
    int maxWidth;


    public KeywordEditor2() {
        textField = new JTextField();
        list = new JList(model = new KeywordListModel());
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        list.setCellRenderer(new IconCellRenderer());
        scroll = new JScrollPane(list);
        maxHeight = scroll.getPreferredSize().height;
        scroll.setVisible(false);
        textField.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                if (list.getSelectedIndex() >= 0) {
                    textField.setText(list.getSelectedValue().toString());
                }
                KeywordEditor2.this.stopCellEditing();
            }
        });
        textField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (!scroll.isVisible()) return;
                final int keyCode = e.getKeyCode();
                switch (keyCode) {
                    case KeyEvent.VK_DOWN:
                        ListScrollingUtil.moveDown(list, e.getModifiersEx());
                        e.consume();
                        break;
                    case KeyEvent.VK_UP:
                        ListScrollingUtil.moveUp(list, e.getModifiersEx());
                        e.consume();
                        break;
                    case KeyEvent.VK_PAGE_DOWN:
                        ListScrollingUtil.movePageDown(list);
                        e.consume();
                        break;
                    case KeyEvent.VK_PAGE_UP:
                        ListScrollingUtil.movePageUp(list);
                        e.consume();
                        break;
                    case KeyEvent.VK_ENTER:
                        break;
                }
            }
        });

        list.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2) {
                    textField.setText(list.getSelectedValue().toString());
                    stopCellEditing();
                }
            }
        });
    }

    @Override
    public boolean isCellEditable(EventObject e) {
        if (e instanceof MouseEvent) {
            return ((MouseEvent) e).getClickCount() >= 2;
        }
        return true;
    }

    @Override
    public boolean stopCellEditing() {
        Container parent = scroll.getParent();
        if (parent != null) {
            parent.remove(scroll);
            parent.repaint();
        }
        return super.stopCellEditing();
    }

    @Override
    public void cancelCellEditing() {
        Container parent = scroll.getParent();
        if (parent != null) {
            parent.remove(scroll);
            parent.repaint();
        }
        super.cancelCellEditing();
    }

    public Object getCellEditorValue() {
        scroll.setVisible(false);
        return textField.getText();
    }

    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        Command cmd = (Command) value;
        textField.setText(cmd.getKeyword());
        textField.getDocument().addDocumentListener(new DocumentListener() {
            public void changedUpdate(DocumentEvent e) {
                textChanged(e);
            }

            public void insertUpdate(DocumentEvent e) {
                textChanged(e);
            }

            public void removeUpdate(DocumentEvent e) {
                textChanged(e);
            }

            private void textChanged(DocumentEvent e) {
                rebuildList();
            }
        });
        Rectangle rect = table.getCellRect(row, column, false);
        Point pt = rect.getLocation();
        SwingUtilities.convertPointToScreen(pt, table);
        SwingUtilities.convertPointFromScreen(pt, table.getRootPane().getLayeredPane());
        Dimension size = scroll.getPreferredSize();
        maxWidth = Math.max(size.width, rect.width);
        pt.y += rect.getHeight();
        table.getRootPane().getLayeredPane().add(scroll);
        scroll.setBounds(pt.x, pt.y, maxWidth, size.height);
        scroll.setVisible(true);
        textField.selectAll();
        return textField;
    }

    private void rebuildList() {
//        textField.get
//        Object selected = list.getSelectedValue();
        model.setLeading(textField.getText());
        list.getSelectionModel().clearSelection();
        if (model.getSize() > 0) {
            scroll.setVisible(true);
            resizeScroll();
            if (!"".equals(textField.getText()))
                list.setSelectedIndex(0);
        } else {
            scroll.setVisible(false);
        }

//        if (selected != null)
//            ListScrollingUtil.selectItem(list, selected);
    }

    private void resizeScroll() {
        int listHeight = list.getPreferredSize().height + 5;
        int height = Math.min(listHeight, maxHeight);
        Rectangle rect = scroll.getBounds();
        rect.height = height;
        scroll.setBounds(rect.x, rect.y, rect.width, rect.height);
    }

    public void beforeRemove() {
        Container parent = scroll.getParent();
        if (parent != null) {
            parent.remove(scroll);
            parent.repaint();
        }
    }

    private class KeywordListModel extends AbstractListModel {
        private Vector<String> allKeywords;
        private Vector<String> keywords;
        private String leading = "";

        public KeywordListModel() {
            allKeywords = KeywordRegistry.getInstance().getKeywordNamesInCategory();
            keywords = (Vector<String>) allKeywords.clone();
        }

        public void setLeading(String value) {
            leading = value;
            int oldSize = keywords.size();
            keywords.clear();
            for (String kw : allKeywords) {
                if (kw.toLowerCase().startsWith(leading.toLowerCase()))
                    keywords.add(kw);
            }
            this.fireContentsChanged(this, 0, oldSize - 1);
        }

        public Object getElementAt(int index) {
            return keywords.get(index);
        }

        public int getSize() {
            return keywords.size();
        }
    }

    private class IconCellRenderer extends DefaultListCellRenderer {
        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            String kw = value.toString();
            Icon icon = HydraUtils.getIconForKeyword(kw);
            this.setIcon(icon);
            return this;
        }
    }
}
